/*
 * Equipo creador por Hector Adrian Valdecantos
 * emai: hvaldecantos@gmail.com
 * 30 de Mayo del 2009
 */
package org.javahispano.javacup.tacticas_aceptadas.hector.equipohectorvaldecantos;

import java.util.LinkedList;

import org.javahispano.javacup.modelo.Comando;
import org.javahispano.javacup.modelo.ComandoGolpearBalon;
import org.javahispano.javacup.modelo.ComandoIrA;
import org.javahispano.javacup.modelo.Constantes;
import org.javahispano.javacup.modelo.Posicion;
import org.javahispano.javacup.modelo.SituacionPartido;

public class Equipo {
	private SituacionPartido sp;
	private Pelota pelota;
	private int[] puedenPatear;
	private final int INDICE_ARQUERO = 0;

	private LinkedList<Comando> comandos;

	public Equipo(SituacionPartido sp, Pelota pelota, LinkedList<Comando> comandos) {
		this.sp = sp;
		this.puedenPatear = sp.puedenRematar();
		this.pelota = pelota;
		this.comandos = comandos;
	}

	public int getINDICE_ARQUERO() {
		return INDICE_ARQUERO;
	}

	/**
	 * Tiene que llamar puedePatear antes
	 * 
	 * @return posicion de pateador
	 */
	public Posicion getPateador() {
		Posicion p = null;
		if (puedePatear())
			p = sp.misJugadores()[puedenPatear[0]];
		return p;
	}

	public Posicion getPosicionJugadorMasLibre() {
		double d, max = 10000;
		int indiceJugadorMasLibre = 0;
		for (int i = 0; i < 11; i++) {
			if (i == INDICE_ARQUERO)
				continue;
			for (int j = 0; j < 10; j++) {
				d = sp.misJugadores()[i].distancia(sp.rivales()[j]);
				if (d < max) {
					max = d;
					indiceJugadorMasLibre = i;
				}
			}
		}
		return sp.misJugadores()[indiceJugadorMasLibre];
	}

	double anguloDeAvance = 0;

	public boolean puedeAvanzarConPelota() {
		final double VARIACION_ANGULO = 70d;
		int cantidadDeRivalesAlFrente = 0;
		int[] indicesRivalesA12Metros = pelota.indicesRivalesSegunDistancia(12);
		int[] indicesRivalesAlFrente = new int[indicesRivalesA12Metros.length];
		boolean puedoAvanzar = false;

		if (indicesRivalesA12Metros.length == 0) {
			if (pelota.getPosicion().getY() < Constantes.centroArcoSup.getY() - 33d) {
				anguloDeAvance = Math.toDegrees(pelota.getPosicion().angulo(Constantes.centroArcoSup));
			}
			return true;
		} else {
			for (int i = 0; i < indicesRivalesA12Metros.length; i++) {
				if (pelota.getPosicion().getY() < (sp.rivales()[indicesRivalesA12Metros[i]].getY() + Constantes.DISTANCIA_CONTROL_BALON + 1.5d)) {
					indicesRivalesAlFrente[cantidadDeRivalesAlFrente++] = indicesRivalesA12Metros[i];
				}
			}
			if (cantidadDeRivalesAlFrente == 0) {
				if (pelota.getPosicion().distancia(sp.rivales()[indicesRivalesA12Metros[0]]) > Constantes.DISTANCIA_CONTROL_BALON + 1.5d) {
					if (pelota.getPosicion().getY() < Constantes.centroArcoSup.getY() - 33d) {
						if (pelota.estaAMetrosLateral(7)) {
							if (pelota.getPosicion().getX() > 0.0d) {
								anguloDeAvance = anguloDeAvance + VARIACION_ANGULO;
							}
							if (pelota.getPosicion().getX() < 0.0d) {
								anguloDeAvance = anguloDeAvance - VARIACION_ANGULO;
							}
						}
					} else {
						anguloDeAvance = Math.toDegrees(pelota.getPosicion().angulo(Constantes.centroArcoSup));
					}
					puedoAvanzar = true;
				}
			} else {
				if (cantidadDeRivalesAlFrente == 1) {
					Posicion rival = sp.rivales()[indicesRivalesAlFrente[0]];
					if (pelota.getPosicion().distancia(rival) > Constantes.DISTANCIA_CONTROL_BALON + 1.5) {
						double ang = Math.toDegrees(pelota.getPosicion().angulo(rival));
						if (ang > 0 && ang < 180) {
							if (pelota.estaAMetrosLateral(4)) {
								return false;
							}
							if (ang > 90) {
								anguloDeAvance = ang - VARIACION_ANGULO;
							} else {
								anguloDeAvance = ang + VARIACION_ANGULO;

							}
						} else {
							anguloDeAvance = Math.toDegrees(pelota.getPosicion().angulo(Constantes.centroArcoSup));
						}
						puedoAvanzar = true;
					}
				}
			}
		}
		return puedoAvanzar;
	}

	public boolean puedeMeterGol() {
		if (pelota.distanciaAlArco() < 33 && (!puedeAvanzarConPelota() || pelota.getPosicion().getY() > Constantes.centroArcoSup.getY() - 15d))
			return true;
		return false;
	}

	public ComandoGolpearBalon patearAlArco(int indiceJugador, double fuerza) {
		return new ComandoGolpearBalon(indiceJugador, Constantes.centroArcoSup, fuerza, pelota.getAnguloGolpeDeGol(indiceJugador, fuerza));
	}

	public ComandoGolpearBalon avanzarConPelota(int indiceJugador) {
		// return new ComandoGolpearBalon(indiceJugador, Constantes.centroArcoSup, 0.35, 0.0);
		// System.out.println(x);
		return new ComandoGolpearBalon(indiceJugador, anguloDeAvance, 0.4, 0.0);
	}

	private int indiceReceptorPace = -1;

	public Comando darPase(int indiceEmisorPase) {// me dio una excepcion
		int[] indicesJugadoresCercanos = pelota.getPosicion().indicesMasCercanos(sp.misJugadores(), indiceEmisorPase, INDICE_ARQUERO);
		double fuerza = .5;
		Posicion p = sp.misJugadores()[indicesJugadoresCercanos[0]];
		indiceReceptorPace = indicesJugadoresCercanos[0];
		double distancia;
		for (int i = 0; i <= 8; i++) { // 0-el mas cercano ... 9-el mas lejano
			distancia = getPateador().distancia(sp.misJugadores()[indicesJugadoresCercanos[i]]);
			if ((getPateador().getY() + 3) < sp.misJugadores()[indicesJugadoresCercanos[i]].getY() && distancia > 7) {
				p = sp.misJugadores()[indicesJugadoresCercanos[i]];
				indiceReceptorPace = indicesJugadoresCercanos[i];
				// fuerza = 1;
				fuerza = fuerzaPatada(distancia);
				break;
			}
		}

		return new ComandoGolpearBalon(indiceEmisorPase, p, fuerza, pelota.anguloGolpeDePase(indiceEmisorPase, fuerza, p, 1.2));
	}

	private double fuerzaPatada(double distancia) {
		return (0.04 * (distancia - 5)) + 0.5;
	}

	/**
	 * Tiene que llamar puedePatear antes
	 * 
	 * @return indice de pateador
	 */
	public int getIndicePateador() {
		int i = -1;
		if (puedePatear())
			i = puedenPatear[0];
		return i;
	}

	/**
	 * Si pueden patear los jugadores, excepto el arquero y no es pelogro de gol
	 * 
	 * @return true or false
	 */
	public boolean puedePatear() {
		this.puedenPatear = sp.puedenRematar();
		return (puedenPatear.length > 0) && (puedenPatear[0] != INDICE_ARQUERO);// && !peligroDeGol;
	}

	public Posicion getPosicionArquero() {
		Posicion puntoFijo = new Posicion(Constantes.centroArcoInf.getX(), Constantes.centroArcoInf.getY() - 2);
		Posicion posicionArquero = Posicion.Interseccion(pelota.getPosicion(), puntoFijo, Constantes.posteIzqArcoInf, Constantes.posteDerArcoInf);

		if (posicionArquero != null) {
			if (posicionArquero.getX() < Constantes.posteIzqArcoInf.getX())
				posicionArquero = new Posicion(Constantes.posteIzqArcoInf.getX(), posicionArquero.getY());
			else if (posicionArquero.getX() > Constantes.posteDerArcoInf.getX())
				posicionArquero = new Posicion(Constantes.posteDerArcoInf.getX(), posicionArquero.getY());
		} else
			posicionArquero = new Posicion(Constantes.centroArcoInf);
		return posicionArquero;
	}

	Posicion pelotaPosicionFuturo = new Posicion();
	Posicion posicionArqueroParaAtajarGol = Constantes.centroArcoInf;
	private boolean peligroDeGol = false;

	public void setComandosArquero() {
		// Comportamiento Arquero (anda bien)
		if (pelota.esPateadaPorRival()) {// y cuando haya cambio de direccion
			pelotaPosicionFuturo = pelota.getPosicionFuturo(7);
			// Si la pelota a futuro paso por dentro del arco
			Posicion gol = Posicion.Interseccion(pelota.getPosicion(), pelotaPosicionFuturo, Constantes.posteIzqArcoInf, Constantes.posteDerArcoInf);
			if ((gol != null) && (gol.getX() >= Constantes.posteIzqArcoInf.getX() && gol.getX() <= Constantes.posteDerArcoInf.getX())) {
				peligroDeGol = true;
				posicionArqueroParaAtajarGol = gol;
			} else {
				peligroDeGol = false;
			}
		}
		// Mover Arquero
		if (peligroDeGol) {
			Posicion arquero = sp.misJugadores()[INDICE_ARQUERO];
			if (pelota.getVelocidad() < 0.9d && pelota.seAcerca(arquero, Constantes.DISTANCIA_PENAL))
				comandos.add(new ComandoIrA(INDICE_ARQUERO, pelota.getPosicion()));
			else
				comandos.add(new ComandoIrA(INDICE_ARQUERO, posicionArqueroParaAtajarGol));
		} else {
			Posicion arquero = sp.misJugadores()[INDICE_ARQUERO];
			if (pelota.seAcerca(arquero, Constantes.DISTANCIA_PENAL)
					&& pelota.indicesRivalesSegunDistancia(Constantes.DISTANCIA_PENAL).length == 0) {
				comandos.add(new ComandoIrA(INDICE_ARQUERO, pelota.getPosicionFuturo(3)));
			} else {
				comandos.add(new ComandoIrA(INDICE_ARQUERO, getPosicionArquero()));
			}
		}
		// Golpear Balon
		if (puedeAvanzarConPelota()) {
			comandos.add(new ComandoGolpearBalon(INDICE_ARQUERO, getPosicionJugadorMasLibre(), 1, true));
		} else {
			if (pelota.getPosicion().getX() < 0) {
				comandos.add(new ComandoGolpearBalon(INDICE_ARQUERO, new Posicion(-34d, -45d), 1, true));
			} else {
				comandos.add(new ComandoGolpearBalon(INDICE_ARQUERO, new Posicion(34d, -45d), 1, true));
			}
		}
	}

	private int indiceJugadorAvanzandoConPelota = -1;

	public void setComandosJugadores() {
		if (indiceJugadorAvanzandoConPelota != -1) {
			comandos.add(new ComandoIrA(indiceJugadorAvanzandoConPelota, pelota.getPosicion()));
		}
		if (indiceReceptorPace != -1) {
			buscarRecibirPase(indiceReceptorPace);
		}
		if (this.puedePatear()) {
			indiceReceptorPace = -1;// ya no hay nadie que tenga que recibir el pase
			indiceJugadorAvanzandoConPelota = -1;
			if (this.puedeMeterGol()) {
				comandos.add(this.patearAlArco(this.getIndicePateador(), 1));
			} else {
				if (this.puedeAvanzarConPelota()) {
					comandos.add(this.avanzarConPelota(this.getIndicePateador()));
					indiceJugadorAvanzandoConPelota = this.getIndicePateador();
					comandos.add(new ComandoIrA(this.getIndicePateador(), pelota.getPosicion()));
				} else {
					comandos.add(this.darPase(this.getIndicePateador()));
				}
			}
		} else {
			int cont = 0;
			for (int i = 0; i < 11; i++) {
				if (i == indiceReceptorPace || i == indiceJugadorAvanzandoConPelota || i == INDICE_ARQUERO) {
					continue;
				}
				Posicion jugador = sp.misJugadores()[i];
				if ((pelota.seAcerca(jugador, 12d) || pelota.getPosicion().distancia(jugador) < 7d) && cont < 3d) {
					comandos.add(new ComandoIrA(i, pelota.getPosicionFuturo(3)));
					cont++;
				} else {

					comandos.add(new ComandoIrA(i, alineacionJuego[i]));
				}
			}
		}
	}

	private void buscarRecibirPase(int indiceReceptorPace) {
		if (sp.misJugadores()[indiceReceptorPace].distancia(pelota.getPosicion()) > 5.0) {
			comandos.add(new ComandoIrA(indiceReceptorPace, pelota.getPosicionFuturo(6)));
		} else {
			comandos.add(new ComandoIrA(indiceReceptorPace, pelota.getPosicionFuturo(3)));
		}
	}

	private static Posicion alineacionJuego[] = new Posicion[] { new Posicion(0.2595419847328244, -50.41044776119403),
			new Posicion(-19.46564885496183, -31.6044776119403), new Posicion(0.2595419847328244, -31.082089552238806),
			new Posicion(19.984732824427482, -31.6044776119403), new Posicion(-11.888111888111888, -13.065610859728507),
			new Posicion(25.678321678321677, -0.23755656108597287), new Posicion(8.321678321678322, -12.115384615384617),
			new Posicion(-24.013986013986013, 4.513574660633484), new Posicion(-15.93006993006993, 32.54524886877828),
			new Posicion(-1.902097902097902, 9.97737556561086), new Posicion(12.717557251908397, 29.51492537313433) };

}
